/*
* Layout.cpp
*
*  Created on: Mar 23, 2011
*      Author: hxu
*/

#include "Layout.h"
#include "Buffer.h"
#include "Wire.h"
#include "TSV.h"

using namespace std;
using namespace Txuh;
using namespace Cxuh;

namespace Cxuh {
	template<class Type> Layout<Type>::Layout() {
		// empty layout, no trees
		trees.clear();
		treenum = 0;
	}

	template<class Type> Layout<Type>::Layout(ifstream& setupstream, ifstream& iclayout) {
		// initiate the layout with input stream buffer, throw(string)
		string templine;
		string tempword;
		trees.clear();
		treenum = 0;
		curSeg = NULL;
		curNode = NULL;

		extractPar(setupstream); // extract parameters

		trees.push_back(new Btree(0)); // first tree, process only this tree
		treenum = 1;
		while (!iclayout.eof()) {
			getline(iclayout, templine);
			if (templine != "") {
				StrTr(templine); // non empty line
			}
		}
		trees[0]->CTS3D();
	}

	template<class Type> Layout<Type>::~Layout() {
		// Auto-generated destructor stub
	}


	template<class Type> void Layout<Type>::StrTr(const string& str1){
		// translate a string according to its content
		string tempstr;
		Btree* tree1 = trees[treenum-1];

		istringstream sstr1(str1);
		sstr1 >> tempstr;

		if (tempstr == "NumPins"){
			// # of sinks declaration
		}
		else if (tempstr == "Sink"){
			// sink index
			int id1;
			sstr1 >> tempstr; //skip :
			sstr1 >> id1;
			curNode = new BtreeNode(id1, LEAF);
		}
		else if (tempstr == "Coordinate"){
			int x1, y1, z1;
			sstr1 >> tempstr; //skip :
			sstr1 >> x1;
			sstr1 >> y1;
			sstr1 >> z1;
			curNode->setXYZ(x1, y1, z1);
		}
		else if (tempstr == "Capacitive"){
			double cap;
			sstr1 >> tempstr; //skip load and :
			sstr1 >> tempstr; //skip load and :
			sstr1 >> cap;
			curNode->setC(cap);
			tree1->addSink(curNode);
		}
		else if (tempstr!="") {
			// ignore empty lines
			//cout << "Invalid Line: " << str1 << endl;
		}

	}

	//template<class Type> Segment<Type>* Layout<Type>::Str2Seg(istringstream& sstr1)throw(int){
	//	// translate a stringstream into a segment
	//	Point<Type>*pt1, *pt2;
	//	Type x[4]; // coordinates (x1,y1, x2,y2)
	//	Segment<Type>* seg1;
	//	int i, z;
	//	double r, c;
	//	int l;
	//
	//	for(i=0;i<4;i++){
	//		sstr1 >> x[i];
	//	}
	//	sstr1 >> z;
	//	sstr1 >> r;
	//	sstr1 >> c;
	//	sstr1 >> l;
	//
	//
	//	pt1 = new Point<Type>(x[0],x[1], z);
	//	pt2 = new Point<Type>(x[2],x[3], z);
	//
	//	try{
	//		seg1 = new Segment<Type>(pt1, pt2, r, c, l);
	//	}
	//	catch(int){
	//		// x, y, or z is equal to or smaller than 0
	//		throw;
	//	}
	//
	//	return seg1;
	//}

	template<class Type> vector<Cxuh::Btree* > Layout<Type>::getTrees(){
		return trees;
	}

	template<class Type> void Layout<Type>::CTS3D(){
		// synthesize all trees with MMM
		for (int i=0;i<=treenum-1;i++){
			trees[i]->CTS3D();
		}
	}

	template<class Type> void Layout<Type>::CTS(){
		// synthesize all trees with MMM
		for (int i=0;i<=treenum-1;i++){
			trees[i]->CTS();
		}
	}

	template<class Type> ostream& operator << (ostream& out, Layout<Type>& obj){
		for(int i = 0; i< obj.treenum; i++){
			out << "Tree: " << obj.trees[i]->getID() << endl;
			out << *(obj.trees[i]) << endl;
		}

		out << "# TSVBOUND " << Btree::TSV_bound_per_tier << endl;
		out << "# SRCZ " << Btree::tier_of_src << endl;
		out << "# BUFR " << Buffer::Rout << endl;
		out << "# BUFC " << Buffer::Cin << endl;
		out << "# BUFD " << Buffer::Dbuf<< endl;
		out << "# WIRER " << Wire::R << endl;
		out << "# WIREC " << Wire::C << endl;
		out << "# TSVR " << TSV::R_unit<< endl;
		out << "# TSVC " << TSV::C_unit<< endl;
		out << "# BUFLOAD " << Buffer::cload_limit<< endl;
		out << endl;

		return out;
	}

	template<class Type> void Layout<Type>::printPaths (ostream& out){
		// print the paths to the sinks
		for(int i = 0; i<= treenum-1; i++){
			out << "Tree: " << trees[i]->getID() << endl;
			//		trees[i]->printPaths(out);
			trees[i]->display4sim(out, 421);
			trees[i]->display4sim(out, 83);
			trees[i]->display4sim(out, 816);
		}
	}

	template<class Type> void Layout<Type>::extractPar(std::ifstream& fs){
		// extract parameters from file stream
		string linestr;

		while (fs.eof() == 0) {
			// parse each line
			getline(fs, linestr);
			parseLine(linestr);
		}
	}

	template<class Type> void Layout<Type>::parseLine(string& strline){
		// parse a line

		if(strline.empty())
			return;

		istringstream sstr(strline);
		string str1, str2;
		sstr >> str1;
		sstr >> str2;

		// translate parameters
		if (str1 == "TSVBOUND") {
			int a = str2int(str2);
			Btree::TSV_bound_per_tier = a;
		} else if (str1 == "SRCZ") {
			int a = str2int(str2);
			Btree::tier_of_src = a;
		} else if (str1 == "BUFR") {
			double a = str2double(str2);
			Buffer::Rout = a;
		} else if (str1 == "BUFC") {
			double a = str2double(str2);
			Buffer::Cin = a;
		} else if (str1 == "BUFD") {
			double a = str2double(str2);
			Buffer::Dbuf = a;
		} else if (str1 == "WIRER") {
			double a = str2double(str2);
			Wire::R = a;
		} else if (str1 == "WIREC") {
			double a = str2double(str2);
			Wire::C = a;
		} else if (str1 == "TSVR") {
			double a = str2double(str2);
			TSV::R_unit = a;
		} else if (str1 == "TSVC") {
			double a = str2double(str2);
			TSV::C_unit = a;
		} else if (str1 == "BUFLOAD") {
			double a = str2double(str2);
			Buffer::cload_limit = a;
		}

	}

}


